﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Timers;
using System.Windows.Controls;
using System.Windows.Threading;
using System.IO;
using System.Media;

using IrrKlang;

namespace MuzičkiFeršterker
{
    [Obsolete("Derecated, use PlayHandler.cs instead")]
    public class Play
    {
        // irrKlang engine
        private ISoundEngine irrEngine;
        private ISound irrSong;
        // nBass engine
        private MediaElement mediaElementEngine;

        // current song refference
        private Song currentSong;

        // common variables
        private bool playing = false;
        private bool paused = false;
        private string songPath;
        private uint pauseTime;

        // graphical elements
        private TextBlock elapsedLabel;
        private TextBlock remainingLabel;
        private TextBlock titleLabel;
        private Slider timeSlider;
        private volatile Engine currentSongEngine = Engine.ERROR;

        // events
        public delegate void RequestNextSong();
        public event RequestNextSong onRequestNextSong;

        Timer timer;

        #region Constructor
        public Play()
        {
            irrEngine = new ISoundEngine();

            timer = new Timer();
            timer.Interval = 10;
            timer.Elapsed += timerTick;
            irrEngine.SoundVolume = 1.0f;
        }
        #endregion

        #region Element sets
        public void SetMediaElement(MediaElement a)
        {
            mediaElementEngine = a;
        }

        public void SetElapsedLabel(TextBlock a)
        {
            elapsedLabel = a;
        }

        public void SetRemainingLabel(TextBlock a)
        {
            remainingLabel = a;
        }

        public void SetTimeSlider(Slider a)
        {
            timeSlider = a;
        }

        public void SetTitleLabel(TextBlock a)
        {
            titleLabel = a;
        }
        #endregion

        #region Function methods
        public void PlayPause()
        {
            if (!File.Exists(songPath))
                return;

            if (playing && !paused)
            {
                pauseTime = irrSong.PlayPosition;
                irrSong.Stop();
                timer.Enabled = false;
                paused = true;
            }
            else
            {
                irrSong = irrEngine.Play2D(songPath, true);
                timer.Enabled = true;
                paused = false;
                if (pauseTime != 0)
                {
                    irrSong.PlayPosition = pauseTime;
                    pauseTime = 0;
                }
            }
            playing = !playing;
        }

        public void PlaySong(Song inputSong)
        {
            if (!File.Exists(inputSong.Path))
                return;

            Console.WriteLine("Song: " + inputSong.Name + "\n    Path:" + inputSong.Path + "\n    Engine:" + inputSong.Engine);

            songPath = inputSong.Path;
            switch (inputSong.Engine)
            {
                default:
                case Engine.ERROR:
                    Console.WriteLine("ERROR / default");
                    return;

                case Engine.irrKlang:
                    Console.WriteLine("irrKlang");
                    StopSong();
                    irrSong = irrEngine.Play2D(songPath, false);
                    if (irrSong == null)
                    {
                        currentSongEngine = Engine.ERROR;
                        return;
                    }

                    if (timeSlider != null)
                        timeSlider.Maximum = millisecondsToSeconds(irrSong.PlayLength);
                    break;

                case Engine.MediaElement:
                    Console.WriteLine("MediaElement");
                    if(mediaElementEngine == null)
                        return;
                    StopSong();
                    try
                    {
                        mediaElementEngine.Source = new Uri(songPath);
                        mediaElementEngine.Play();
                    }
                    catch
                    {
                        currentSongEngine = Engine.ERROR;
                        return;
                    }
                    
                    if(timeSlider != null && mediaElementEngine.NaturalDuration.HasTimeSpan)
                        timeSlider.Maximum = (int)mediaElementEngine.NaturalDuration.TimeSpan.TotalSeconds;
                    break;
            }
            currentSongEngine = inputSong.Engine;
            currentSong = inputSong;

            if (titleLabel != null)
                titleLabel.Text = inputSong.Name;
            timer.Enabled = true;
            playing = true;
        }

        public void SetSongPosition(int a)
        {
            if (!paused)
            {
                if (a != millisecondsToSeconds(irrSong.PlayPosition))
                    irrSong.PlayPosition = (uint)a * 1000;
            }
            else
            {
                pauseTime = (uint)a*1000;
            }
        }

        public void StopSong()
        {
            switch (currentSongEngine)
            { 
                default:
                case Engine.ERROR:
                    return;

                case Engine.irrKlang:
                    if (playing)
                    {
                        irrSong.Stop();
                        playing = false;
                    }
                    return;

                case Engine.MediaElement:
                    if (playing)
                    {
                        mediaElementEngine.Stop();
                        playing = false;
                    }
                    return;
            }
        }

        public void SetVolume(float volume)
        {
            irrEngine.SoundVolume = volume;
        }

        public void SetBalance(float a)
        {
            if(irrSong != null)
                irrSong.Pan = a;
        }
        #endregion

        #region Convert methods
        private string millisecondsToString(uint ms)
        {
            string vrni = "";

            ms = ms - (ms % 1000);
            ms /= 1000;
            vrni = ms.ToString();
            string minute = (ms / 60).ToString();
            if (minute.Length < 2)
                minute = "0" + minute;
            string sekunde = (ms - (60 * (ms / 60))).ToString();
            if (sekunde.Length < 2)
                sekunde = "0" + sekunde;

            vrni = minute + ":" + sekunde;
            return vrni;
        }

        private int millisecondsToSeconds(uint ms)
        {
            ms = ms - (ms % 1000);
            return (int)ms / 1000;
        }
        #endregion

        #region Timer tick methods
        private void timerTick(object o, ElapsedEventArgs e)
        {
            string elapsedTime = "";
            string remainingTime = "";
            int playPosition = 0;

            switch (currentSongEngine)
            { 
                case Engine.ERROR:
                    return;

                case Engine.irrKlang:
                    elapsedTime = millisecondsToString(irrSong.PlayPosition);
                    remainingTime = millisecondsToString(irrSong.PlayLength - irrSong.PlayPosition);
                    playPosition = millisecondsToSeconds(irrSong.PlayPosition);
                    break;

                case Engine.MediaElement:
                    try
                    {
                        Dispatcher.CurrentDispatcher.Invoke((Action)delegate()
                        {
                            try
                            {
                                elapsedLabel.Dispatcher.Invoke((Action)delegate()
                                {
                                    elapsedTime = millisecondsToString((uint)mediaElementEngine.Position.TotalMilliseconds);
                                });
                            }
                            catch (Exception exp)
                            {
                                Console.WriteLine(exp.Message.ToString());
                            }
                        });
                        Dispatcher.CurrentDispatcher.Invoke((Action)delegate()
                        {
                            try
                            {
                                elapsedLabel.Dispatcher.Invoke((Action)delegate()
                                {
                                    try
                                    {
                                        double a = mediaElementEngine.NaturalDuration.TimeSpan.TotalMilliseconds;
                                        double b = currentSong.LengthInt;
                                        remainingTime = millisecondsToString((uint)(a - b));
                                    }
                                    catch (Exception lasdjfčlajskldsdghskdjghklajdshfkljashfkl)
                                    {
                                        Console.WriteLine(lasdjfčlajskldsdghskdjghklajdshfkljashfkl.Message.ToString());
                                    }
                                });
                            }
                            catch (Exception exp)
                            {
                                Console.WriteLine(exp.Message.ToString());
                            }
                        });
                    }
                    catch (Exception exception)
                    {
                        Console.WriteLine(exception.Message.ToString());
                    }
                    playPosition = 0;
                    break;
            }

            if (elapsedLabel != null)
            {
                elapsedLabel.Dispatcher.Invoke((Action)delegate() { elapsedLabel.Text = elapsedTime; });
            }

            if (remainingLabel != null)
            {
                remainingLabel.Dispatcher.Invoke((Action)delegate() { remainingLabel.Text = remainingTime; });
            }

            if (timeSlider != null)
            {
                timeSlider.Dispatcher.Invoke((Action)delegate() { timeSlider.Value = playPosition; });
            }


            switch (currentSongEngine)
            {
                case Engine.ERROR:
                    return;

                case Engine.irrKlang:
                    if (irrSong.Finished)
                        onRequestNextSong(); 
                    break;

                case Engine.MediaElement:
                    
                    break;
            }
        }
        #endregion

        #region GetSet Properties
        public int PlayPosition
        {
            get { return millisecondsToSeconds(irrSong.PlayPosition); }
        }
        #endregion
    }
}
